#pragma once
#ifndef ENGINE_H_
#define ENGINE_H_

#include "baseobject.h"

/*! \mainpage EPOC Index Page
 *
 * \section intro_sec Introduction
 *
 * N / A
 *
 * \section install_sec Your first EPOC application
 *
 * \subsection step1 N / A
 *
 * \subsection step2 N / A
 *  
 */

namespace EPOC
{
	class TextureSDL;

	/**
	* Engine core class. 
	* This class is the center of all EPOC applications
	*/
	class Engine : public BaseObject
	{
	public:
		
		/**
		* Contructor
		* Resets all members to the default values
		*/
		Engine();
		
		/**
		* Destructor
		* Calls the cleanup method.
		* @see Cleanup()
		*/
		virtual ~Engine();
	 
		/**
		* Cleans up all relevant data
		* @see ~Engine()
		*/
		virtual void Cleanup();	

		/**
		* Fires up the application
		* @param sTitle the title of the application window
		* @param nWidth the width of the application window
		* @param nHeight the height of the application window
		* @param bFullScreen fullscreen window enabled or disabled
		* @see Initialize()
		*/
		virtual void Start(std::string sTitle = "EPOC Application", int nWidth = 800, int nHeight = 600, bool bFullScreen = false);
		
		virtual void Start(std::string sTitle, int nWidth, int nHeight, int nDeviceIndex, Uint32 nSdlWindowFlags, Uint32 nSdlRendererFlags);
		
		/**
		* A pure virtual memeber
		* Initializes the application for use
		* @see Start()
		* @return true if the initiaization succeeded and false if it didn't
		*/
		virtual bool Initialize() = 0;
		
		/**
		* A pure virtual memeber
		* updates the application
		* @remark This function is called once per frame.
		* @param fTimeDelta the time that has passed since last update, measured in milliseconds
		* @return true if the update succeeded and false if it didn't
		*/
		virtual bool Update(float fTimeDelta) = 0;

		/**
		* A pure virtual memeber
		* Prepares and renders the application contents for presentation
		* @param pDestSurface the surface to wich the content should be rendered to
		*/
		virtual void Render( SDL_Renderer* pRenderer ) = 0;

		/**
		* Is called when window is activated
		*/
		virtual void NotifyWindowActive() {}	// window is active again
		
		/**
		* Is called when window is inactivated
		*/
		virtual void NotifyWindowInactive() {}	// window is inactive
	 
		/**
		* Sets the title of the window
		* @param sTitle the new title of the window
		*/
		void SetTitle(std::string sTitle);
		
		/**
		* returns the title of the window
		* @return pointer to the string containing the title of the window
		*/
		inline const std::string* GetTitle() { return &m_sTitle;}

		/**
		* returns the SDL surface at wich the content is rendered to
		* @return pointer to the SDL surface used by the application
		*/
		inline TextureSDL* GetSurface(){ return m_pScreen;}

		/**
		* returns the last frames per second measurement
		* @return float containing the last frames per second measurement
		*/
		inline int GetFPS() { return m_nCurrentFPS;}

		/**
		* returns the last time between updates
		* @return float containing time delta
		*/
		inline float GetTimeDelta() { return m_fTimeDelta;}

		/**
		* sets which key to use as quit-key
		* @param nQuitKey the SDLK enumeration key to use as quit-key
		*/
		inline void SetQuitKey(int nQuitKey = SDLK_ESCAPE) { m_nQuitKey = nQuitKey;}


		inline int GetWindowWidth() { return m_nWidth;}
		inline int GetWindowHeight() { return m_nHeight;}
		
		//inline RENDER_MODE GetRenderMode() { return m_nRenderMode;}
		//inline const SDL_VideoInfo* GetVideoInformation() { return m_pVideoInfo;}

		inline bool IsFPSCapEnabled()				{ return m_bFPSCapEnabled;}
		inline void SetFPSCapEnabled(bool bStatus)	{ m_bFPSCapEnabled = bStatus;}

		inline unsigned int GetFPSCap()				{ return m_nFPSCap;}
		inline void SetFPSCap(int nFPSCap)			{ m_nFPSCap = nFPSCap;}


	protected:
		
		/**
		* handles the updating routine
		* @return true if the update succeeded and false if it didn't
		* @remark This function is called once per frame
		*/
		virtual bool DoUpdate();

		/** 
		* handles the rendering and FPS calculations
		* 
		*/
		virtual void DoRender();
		
		/** 
		* handles all core engine controller inputs
		* @remark This function is called once per frame
		*/
		virtual void DoEvents();


		//TODO: Update these comments
		/** 
		* sets the videomode to use
		* @param nWidth the width of the renderwindow
		* @param nHeight the height of the renderwindow
		* @param bFullScreen if fullscreen should be used or not
		* @param nBpp the bitdepth to use
		* @param nFlags SDL flags for renderwindow
		* @return true if the method succeeded and false if it didn't
		*/
		virtual bool CreateWindowAndRenderer(std::string sTitle, int nWidth, int nHeight, int nDeviceIndex = -1, Uint32 nFlags = SDL_WINDOW_OPENGL, Uint32 nRendererFlags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);

		
	protected:
		//RENDER_MODE m_nRenderMode;		///< The render mode to be used, pure sdl or opengl
		bool m_bFPSCapEnabled;			///< Is the framerate capped?
		bool m_bQuit;					///< Has quit been called?
		bool m_bMinimized;				///< Is the window minimized?
		bool m_bFullScreen;				///< Is the window in fullscreen?
		bool m_bMouseFocus;
		bool m_bKeyboardFocus;
		bool m_bAudioSupport;
		
		unsigned int m_nFPSCap;			///< The maximum framerate allowed
		
		int m_nWidth;					///< Window width
		int m_nHeight;					///< Window height
		
		int m_nFPSTickCounter;			///< Tick counter
		int m_nFPSCounter;				///< Frame rate counter
		int m_nCurrentFPS;				///< Stores the last calculated frame rate.
		int m_nQuitKey;					///< The key enumeration that quits the program

		float m_fTimeDelta;
		
		long m_lLastTick;					///< Last iteration's tick value
		std::string m_sTitle;				///< The title of the window
		//const SDL_VideoInfo *m_pVideoInfo;	///< Information about the rendering capabilities
		TextureSDL* m_pScreen;				///< Screen surface
		SDL_Window*		m_pWindow;			///< Main Window
		SDL_Renderer*	m_pRenderer;		///< Renderer
	};

}; // namespace EPOC

#endif